/* Représente un arbre DTD en mémoire.
 */


#ifndef _DTD_TREE
#define _DTD_TREE


#include "DtdComposite.h"
#include "DtdElement.h"
#include "DtdDeclaration.h"

#include <map>
#include <string>
#include <set>


class DtdTree
{
	public :
		/* Constructeur */
		DtdTree();

		~DtdTree();

		/* Ajoute une déclaration à la liste des éléments.
		 * L'élément ajouté ne doit pas déjà être présent dans l'arbre.
		 * Renvoie true si l'opération c'est bien passé, 'false' sinon
		 * (car un élément de même nom est déjà dans l'arbre).
		 */
		bool addDeclaration(DtdDeclaration *p_dec);

		/* Structure les élément en un arbre. Si tout se passe bien,
		 * true est renvoyé, sinon, false est renvoyé
		 */
		bool buildTreeStructure();

		/* TODO :
		bool checkAllDeclarations(DtdDeclaration **p_dec_err);
		*/

		/* Renvoie le fichier DTD sous la forme d'une chaine de caractères bien
		 * structurée.
		 */
		std::string getDtdAsString() const;

		/* Obtenir l'expression régulière associé à une déclaration.
		 * Renvoie true si p_elmName correspond à un élément connue, 'false' sinon.
		 */
		bool getDtdRegex(const std::string &p_elmName, std::string &s) const;

		/* Obtenir la liste des nom d'attribut sous la forme d'un tableau.
		 * Renvoie true si p_elmName correspond à un élément connue, 'false' sinon.
		 */
		bool getAttrSet(const std::string &p_elmName, std::set<std::string> &attrSet) const;

	private :
		/* Liste des éléments dans l'abre */
		std::map< std::string, DtdDeclaration* > elements;

		/* Direction dans laquelle on parcourt l'arbre */
		enum TravDir
		{
			UP,
			DOWN
		};

	private :
		/* Ajoute à la chaine de caractère une ligne contenant la chaine
		 * de caractère associée à un élément :
		 * <!ELEMENT ... ... >
		 */
		 void addElement(const DtdDeclaration *p_dec, std::string& s, bool p_regex=false) const;

		 /* Renvoie le caractère associée à une cardinalité */
		 void addCardChar(enum NodeCard c, std::string &s) const;

		 /* Ajoute la déclaration d'un attribut à une chaine de caractère :
		  * <!ATTLIST element-name attribute-name CDATA #IMPLIED >
		  */
		 void addAttribut(const std::string &p_elemName, const std::string &p_attrName,
		 	std::string &s) const;
};


#endif
